package session.stateless.SCM;

import entity.SCM.PickingOrder.State;
import entity.SCM.ProductBalance;
import entity.CRM.SaleOrder;
import entity.SCM.DeliveryOrder;
import entity.SCM.PackingOrder;
import entity.SCM.PickingOrder;
import entity.SCM.ProductLine;
import entity.SCM.ShippingOrder;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

@Stateless
public class DeliveryOrderBean implements DeliveryOrderBeanLocal {
    
    @PersistenceContext()
    EntityManager em;
    
    DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd");
    
    @Override
    public List<ProductBalance> getProduct() {
        Query q = em.createQuery("SELECT c FROM Product c");
        
        return q.getResultList();
    }

    @Override
    public Long createDeliveryOrder(Long saleOrderId) {
        
        DeliveryOrder deliveryOrder = new DeliveryOrder();
        
        SaleOrder saleOrder = em.find(SaleOrder.class, saleOrderId);
        if(saleOrder==null){
            System.out.println("Sale Order does not exist!");   
            return null;
        }
        else{
            Date date = new Date();
            deliveryOrder.setDeliveryDate(dateFormat.format(date));
            deliveryOrder.setDeliveryState(DeliveryOrder.State.Pending);
            deliveryOrder.setSaleOrder(saleOrder);
            em.persist(deliveryOrder);
            em.flush();
            List<DeliveryOrder> deliveryOrders = deliveryOrder.getSaleOrder().getDeliveryOrders();
            deliveryOrders.add(deliveryOrder);
            deliveryOrder.getSaleOrder().setDeliveryOrders(deliveryOrders);
            em.flush();
            
            return deliveryOrder.getId();
        }
    }

    @Override
    public Long createPickingOrder(Long deliveryOrderId, List<ProductLine> productLines) {
        PickingOrder pickingOrder = new PickingOrder();
        
        DeliveryOrder deliveryOrder = em.find(DeliveryOrder.class, deliveryOrderId);
        if(deliveryOrder==null){
            System.out.println("Delivery Order does not exist!");   
            return null;
        }
        else{
            Date date = new Date();
            pickingOrder.setPickingDate(dateFormat.format(date));
            pickingOrder.setPickingState(PickingOrder.State.Pending);
            pickingOrder.setDeliveryOrder(deliveryOrder);
            pickingOrder.setProductLines(productLines);
            em.persist(pickingOrder);
            em.flush();
            
            deliveryOrder.setPickingOrder(pickingOrder);
            em.flush();
            
            return pickingOrder.getId();
        }
    }

    @Override
    public Long createPackingOrder(Long pickingOrderId) {
        PickingOrder pickingOrder = em.find(PickingOrder.class, pickingOrderId);
        DeliveryOrder deliveryOrder=pickingOrder.getDeliveryOrder();
        PackingOrder packingOrder = new PackingOrder();
        
        Date date = new Date();
        packingOrder.setPackingDate(dateFormat.format(date));
        packingOrder.setPackingState(PackingOrder.State.Pending);
        packingOrder.setDeliveryOrder(pickingOrder.getDeliveryOrder());
        em.persist(packingOrder);
        em.flush();
        deliveryOrder.setPackingOrder(packingOrder);
        em.flush();

        return packingOrder.getId();
    }

    @Override
    public Long createShippingOrder(Long packingOrderId) {
        PackingOrder packingOrder = em.find(PackingOrder.class, packingOrderId);
        ShippingOrder shippingOrder = new ShippingOrder();
        
        Date date = new Date();
        shippingOrder.setShippingDate(dateFormat.format(date));
        shippingOrder.setShippingState(ShippingOrder.State.Success);
        shippingOrder.setDeliveryOrder(packingOrder.getDeliveryOrder());
        em.persist(shippingOrder);
        
        em.flush();
        packingOrder.getDeliveryOrder().setShippingOrder(shippingOrder);
        em.flush();
            
        return shippingOrder.getId();        
    }

    @Override
    public ProductLine createProductLine(String productType, Long quantity, Double finalPrice) {
        ProductLine productLine = new ProductLine();
        ProductBalance product = em.find(ProductBalance.class, productType);
        productLine.setProduct(product);
        productLine.setFinalPrice(finalPrice);
        productLine.setQuantity(quantity);
        
        em.persist(productLine);
        em.flush();
        
        return productLine;
    }

    @Override
    public boolean processDeliveryOrder(Long deliveryOrderId) {
        
        DeliveryOrder deliveryOrder = em.find(DeliveryOrder.class, deliveryOrderId);
        if(deliveryOrder==null){
            System.out.println("Delivery Order does not exist!");   
            return false;
        }
        else{
            if(deliveryOrder.getDeliveryState().equals(DeliveryOrder.State.Pending)&&
               deliveryOrder.getPickingOrder().getPickingState().equals(PickingOrder.State.Success)&&
               deliveryOrder.getPackingOrder().getPackingState().equals(PackingOrder.State.Success)&&
               deliveryOrder.getShippingOrder().getShippingState().equals(ShippingOrder.State.Success)){
                deliveryOrder.setDeliveryState(DeliveryOrder.State.Success);
                em.flush();
                return true;
            }else{
                System.out.println("ProcessDeliveryOrder:: Error Occurs!");
                return false;
            }
        }
    }


    @Override
    public boolean processPackingOrder(Long packingId) {
        PackingOrder packingOrder = em.find(PackingOrder.class, packingId);
        if(packingOrder==null){
            System.out.println("Packing Order does not exist!");   
            return false;
        }
        else{
            if(packingOrder.getPackingState().equals(PackingOrder.State.Pending)&&
               packingOrder.getDeliveryOrder().getDeliveryState().equals(DeliveryOrder.State.Pending)&&
               packingOrder.getDeliveryOrder().getPickingOrder().getPickingState().equals(PickingOrder.State.Success)){
                
                packingOrder.setPackingState(PackingOrder.State.Success);
                em.flush();
                return true;
            }else{
                System.out.println("ProcessPackingOrder:: Error Occurs!");
                return false;
            }
        }
    }

    @Override
    public boolean processShippingOrder(Long shippingId) {
        ShippingOrder shippingOrder = em.find(ShippingOrder.class, shippingId);
        if(shippingOrder==null){
            System.out.println("Shipping Order does not exist!");   
            return false;
        }
        else{
            if(shippingOrder.getShippingState().equals(ShippingOrder.State.Pending)&&
               shippingOrder.getDeliveryOrder().getDeliveryState().equals(DeliveryOrder.State.Pending)&&
               shippingOrder.getDeliveryOrder().getPickingOrder().getPickingState().equals(PickingOrder.State.Success)&&
               shippingOrder.getDeliveryOrder().getPackingOrder().getPackingState().equals(PackingOrder.State.Success)){
                
                shippingOrder.setShippingState(ShippingOrder.State.Success);
                em.flush();
                return true;
            }else{
                System.out.println("ProcessShippingOrder:: Error Occurs!");
                return false;
            }
        }
    }

    @Override
    public boolean deletedDeliveryOrder(Long deliveryOrderId) {
        
        DeliveryOrder deliveryOrder = em.find(DeliveryOrder.class, deliveryOrderId);
        if(deliveryOrder==null){
            System.out.println("This Delivery Order does not exist!");
            return false;
        }
        else{
            if(deliveryOrder.getPickingOrder()!=null){
                deliveryOrder.getPickingOrder().setPickingState(PickingOrder.State.Deleted);
            }
            if(deliveryOrder.getPackingOrder()!=null){
                deliveryOrder.getPackingOrder().setPackingState(PackingOrder.State.Deleted);
            }
            if(deliveryOrder.getShippingOrder()!=null){
                deliveryOrder.getShippingOrder().setShippingState(ShippingOrder.State.Deleted);
            }
            deliveryOrder.setDeliveryState(DeliveryOrder.State.Deleted);
            em.flush();
            return true;
        }
    }

    @Override
    public boolean deletedPickingOrder(Long pickingId) {
        
        PickingOrder pickingOrder = em.find(PickingOrder.class, pickingId);
        if(pickingOrder==null){
            System.out.println("This Picking Order does not exist!");
            return false;
        }
        else{
            pickingOrder.setPickingState(PickingOrder.State.Deleted);
            em.flush();
            return true;
        }
    }

    @Override
    public boolean deletedPackingOrder(Long packingId) {
        
        PackingOrder packingOrder = em.find(PackingOrder.class, packingId);
        if(packingOrder==null){
            System.out.println("This Packing Order does not exist!");
            return false;
        }
        else{
            packingOrder.setPackingState(PackingOrder.State.Deleted);
            em.flush();
            return true;
        }
    }

    @Override
    public boolean deletedShippingOrder(Long shippingId) {
        
        ShippingOrder shippingOrder = em.find(ShippingOrder.class, shippingId);
        if(shippingOrder==null){
            System.out.println("This Shipping Order does not exist!");
            return false;
        }
        else{
            shippingOrder.setShippingState(ShippingOrder.State.Deleted);
            em.flush();
            return true;
        }
    }

    @Override
    public List<DeliveryOrder> getDeliveryOrder() {
        
//        Query q =em.createQuery("SELECT c FROM DeliveryOrder c" + "WHERE c.deliverystate = 'Pending' OR c.deliverystate= 'Success'");    
//        return q.getResultList();
        
        Query q =em.createQuery("SELECT c FROM DeliveryOrder c");
        List<DeliveryOrder> deliveryOrders = q.getResultList();
        
        for(int i =0; i<deliveryOrders.size(); i++){
            if(deliveryOrders.get(i).getDeliveryState().equals(DeliveryOrder.State.Deleted)){
                deliveryOrders.remove(i);
                i--;
            }
        }
        
        return deliveryOrders;
    }

    @Override
    public List<DeliveryOrder> getSuccessDeliveryOrder() {
        
        Query q =em.createQuery("SELECT c FROM DeliveryOrder c WHERE c.deliveryState= :deliveryState");
        q.setParameter("deliveryState", DeliveryOrder.State.Success);
        
            return q.getResultList();
        
        
   }

    @Override
    public List<PickingOrder> getPickingOrder() {
        
//        Query q =em.createQuery("SELECT c FROM PickingOrder c" + "WHERE c.pickingstate = 'Pending' OR c.pickingstate= 'Success'");   
//        return q.getResultList();
        
        Query q =em.createQuery("SELECT c FROM DeliveryOrder c");
        List<PickingOrder> pickingOrders = q.getResultList();
        
        for(int i =0; i<pickingOrders.size(); i++){
            if(pickingOrders.get(i).getPickingState().equals(PickingOrder.State.Deleted)){
                pickingOrders.remove(i);
                i--;
            }
        }
        
        return pickingOrders;
    }

    @Override
    public List<PackingOrder> getPackingOrder() {
        
//        Query q =em.createQuery("SELECT c FROM PackingOrder c" + "WHERE c.packingstate = 'Pending' OR c.packingstate= 'Success'");      
//        return q.getResultList();
        
        Query q =em.createQuery("SELECT c FROM DeliveryOrder c");
        List<PackingOrder> packingOrders = q.getResultList();
        
        for(int i =0; i<packingOrders.size(); i++){
            if(packingOrders.get(i).getPackingState().equals(PackingOrder.State.Deleted)){
                packingOrders.remove(i);
                i--;
            }
        }
        
        return packingOrders;
    }

    @Override
    public List<ShippingOrder> getShippingOrder() {
        
//        Query q =em.createQuery("SELECT c FROM ShippingOrder c" + "WHERE c.shippingstate = 'Pending' OR c.shippingstate= 'Success'");      
//        return q.getResultList();
        
        Query q =em.createQuery("SELECT c FROM DeliveryOrder c");
        List<ShippingOrder> shippingOrders = q.getResultList();
        
        for(int i =0; i<shippingOrders.size(); i++){
            if(shippingOrders.get(i).getShippingState().equals(ShippingOrder.State.Deleted)){
                shippingOrders.remove(i);
                i--;
            }
        }
        
        return shippingOrders;
    }

    @Override
    public ProductBalance findProduct(String productType) {
        ProductBalance product = em.find(ProductBalance.class, productType);
        return product;
    }

    @Override
    public boolean isPickingOrder_Success(Long pickingId) {
        PickingOrder pickingOrder= em.find(PickingOrder.class, pickingId);
        if (pickingOrder.getPickingState()==PickingOrder.State.Success)
            return true;
        else return false;
    }

    @Override
    public boolean isPackingOrder_Success(Long packingId) {
        PackingOrder packingOrder= em.find(PackingOrder.class, packingId);
        if (packingOrder.getPackingState()==PackingOrder.State.Success)
        {
            System.out.println("packing is actually successful and pass");
            return true;
        }
        else 
            return false;        
    }

    @Override
    public boolean isShippingOrder_Success(Long shippingId) {
        ShippingOrder shippingOrder= em.find(ShippingOrder.class, shippingId);
        if (shippingOrder.getShippingState()==ShippingOrder.State.Success)
            return true;
        else return false;
    }

    @Override
    public PickingOrder findPickingOrder(Long pickingOrderId) {
        return (PickingOrder) em.find(PickingOrder.class, pickingOrderId);
    }

    @Override
    public PackingOrder findPackingOrder(Long packingOrderId) {
        return (PackingOrder) em.find(PackingOrder.class, packingOrderId);
    }

    @Override
    public ShippingOrder findShippingOrder(Long shippingOrderId) {
        return (ShippingOrder) em.find(ShippingOrder.class, shippingOrderId);
    }
    
    
    public void updatePickingStatus(Long pickingOrderId, State state) {
        PickingOrder pickingOrder = em.find(PickingOrder.class, pickingOrderId);
        pickingOrder.setPickingState(state);
        em.flush();
    }
    
    public void updatePackingStatus(Long packingOrderId, PackingOrder.State state) {
        PackingOrder packingOrder = em.find(PackingOrder.class, packingOrderId);
        packingOrder.setPackingState(state);
        em.flush();
    }

    public void updateShippingStatus(Long shippingOrderId, ShippingOrder.State state) {
        ShippingOrder shippingOrder= em.find(ShippingOrder.class, shippingOrderId);
        shippingOrder.setShippingState(state);
        
        if (shippingOrder.getShippingState()==ShippingOrder.State.Success)
        {
            this.updateDeliveryStatus(shippingOrder.getDeliveryOrder().getId(), DeliveryOrder.State.Success);
        }
        em.flush();
    }

    public void updateDeliveryStatus(Long id, DeliveryOrder.State state) {
        DeliveryOrder deliveryOrder=em.find(DeliveryOrder.class, id);
        deliveryOrder.setDeliveryState(state);
        em.flush();
    }

    
}
